﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using AbstraX.ClientInterfaces;
using System.ServiceModel.DomainServices.Client;
using SolutionFramework.Service;
using AbstraX.BindingsTreeEntities;
using System.Linq;
using AbstraX.ViewModels.BindingsTree;
using AbstraX.Service;
using System.Diagnostics;
using System.Windows.Media.Imaging;
using MvvmTreeView.Converters;

namespace PipelineBuilderClient.Services
{
    public class BindingsTreeService : IBindingsTreeService
    {
        private BindingsTreeContext context;
        private BindingsTreeEntityCollection<BindingsTreeEntity> bindingsTrees;

        public BindingsTreeService()
        {
            context = new BindingsTreeContext();
        }

        public IBindingsTreeCollection BindingsTrees
        {
            get 
            {
                if (bindingsTrees == null)
                {
                    bindingsTrees = new BindingsTreeEntityCollection<BindingsTreeEntity>();

                    var query = context.GetBindingsTreeForElementIDQuery("test");
                    var loadOp = context.Load<BindingsTreeEntity>(query);

                    loadOp.Completed += (s, e) =>
                    {
                        context.BindingsTreeEntities.ToList<BindingsTreeEntity>().ForEach(t => bindingsTrees.Add(t));
                    };

                }

                return bindingsTrees;
            }
        }

        private void AddChildren<T>(EntityQuery<T> query, BindingsTreeEntityCollection<Entity> children) where T : Entity
        {
            var loadOpbindingsTreeEntity = context.Load<T>(query, (rootsResult) =>
            {
                foreach (object childEntity in rootsResult.Entities)
                {
                    children.Add((T)childEntity);
                }
            }
            , null);
        }

        public BindingsTreeEntityCollection<Entity> LoadChildren<T>(Entity parentEntity)
        {
            //BindingsTree
            //  BindingsTreeNode
            //    Folder
            //      Element
            //      DataContext
            //          Property
            //      PropertyBinding
            //        AttributeProperty
            //          AbstraXBindingSource
            //          QueryBindingSource

            var children = new BindingsTreeEntityCollection<Entity>();

            switch (parentEntity.GetType().Name)
            {
                case "BindingsTreeEntity":

                    var bindingsTreeEntity = (BindingsTreeEntity)parentEntity;

                    AddChildren<BindingsTreeNode>(context.GetRootBindingNodesForBindingsTreeQuery(bindingsTreeEntity.ID), children);

                    break;

                case "BindingsTreeNode":

                    var bindingsTreeNode = (BindingsTreeNode)parentEntity;

                    AddChildren<Folder>(context.GetParentSourceElementForBindingsTreeNodeQuery(bindingsTreeNode.ID), children);
                    AddChildren<Folder>(context.GetDataContextListForBindingsTreeNodeQuery(bindingsTreeNode.ID), children);
                    AddChildren<Folder>(context.GetPropertyBindingsForBindingsTreeNodeQuery(bindingsTreeNode.ID), children);
                    AddChildren<Folder>(context.GetChildNodesForBindingsTreeNodeQuery(bindingsTreeNode.ID), children);

                    break;

                case "Folder":

                    var folder = (Folder)parentEntity;

                    switch (folder.Name)
                    {
                        case BindingsFolderNames.BindingsSource:
                            AddChildren<AbstraXBindingSource>(context.GetAbstraXBindingSourceForBindingSourceQuery(folder.ID), children);
                            AddChildren<QueryBindingSource>(context.GetQueryBindingSourceForBindingSourceQuery(folder.ID), children);
                            break;
                        case BindingsFolderNames.ParentSourceElement:
                            AddChildren<Element>(context.GetElementForParentSourceElementQuery(folder.ID), children);
                            break;
                        case BindingsFolderNames.DataContext:
                            AddChildren<DataContextObject>(context.GetDataContextForDataContextListQuery(folder.ID), children);
                            break;
                        case BindingsFolderNames.ContextObject:
                            AddChildren<Element>(context.GetElementForContextObjectQuery(folder.ID), children);
                            break;
                        case BindingsFolderNames.SupportedOperations:
                            AddChildren<Element>(context.GetElementForContextObjectQuery(folder.ID), children);
                            break;
                        case BindingsFolderNames.RemoteCalls:
                            AddChildren<Operation>(context.GetOperationForRemoteCallQuery(folder.ID), children);
                            break;
                        case BindingsFolderNames.PropertyBindings:
                            AddChildren<PropertyBinding>(context.GetPropertyBindingForPropertyBindingsQuery(folder.ID), children);
                            break;
                        case BindingsFolderNames.ChildNodes:
                            AddChildren<BindingsTreeNode>(context.GetChildNodeForChildNodesQuery(folder.ID), children);
                            AddChildren<BindingsTreeNodeReference>(context.GetChildNodeReferencesForChildNodesQuery(folder.ID), children);
                            break;
                        default:
                            Debugger.Break();
                            break;
                    }

                    break;

                case "Element":

                    Debugger.Break();
                    break;

                case "DataContextObject":

                    var dataContextObject = (DataContextObject)parentEntity;

                    AddChildren<Folder>(context.GetContextObjectForDataContextQuery(dataContextObject.ID), children);

                    break;

                case "NodeProperty":

                    Debugger.Break();
                    break;

                case "PropertyBinding":

                    var propertyBinding = (PropertyBinding)parentEntity;

                    AddChildren<AttributeProperty>(context.GetPropertyForPropertyBindingQuery(propertyBinding.ID), children);
                    AddChildren<Folder>(context.GetBindingSourceForPropertyBindingQuery(propertyBinding.ID), children);
                    AddChildren<NodeProperty>(context.GetBindingModeForPropertyBindingQuery(propertyBinding.ID), children);

                    break;

                case "AttributeProperty":

                    var attributeProperty = (AttributeProperty)parentEntity;
                    break;

                case "AbstraXBindingSource":

                    var abstraXBindingSource = (AbstraXBindingSource)parentEntity;

                    AddChildren<AttributeProperty>(context.GetBindingAttributeForAbstraXBindingSourceQuery(abstraXBindingSource.ID), children);
                    AddChildren<NodeProperty>(context.GetIsSearchableForAbstraXBindingSourceQuery(abstraXBindingSource.ID), children);

                    break;

                case "QueryBindingSource":

                    var queryBindingSource = (QueryBindingSource)parentEntity;

                    break;

                default:
                    Debugger.Break();
                    break;
            }

            return children;
        }

        public BitmapImage LoadImageForItemType(string itemType)
        {
            if (itemType == "BindingsTreeNodeReference")
            {
                itemType = "BindingsTreeNode";
            }

            var stream = this.GetType().Assembly.GetManifestResourceStream("PipelineBuilderClient.Resources.Images." + itemType + ".png");
            var bitmap = new BitmapImage();
            bitmap.SetSource(stream); 

            return bitmap;
        }

        public byte[] LoadShortcutImage()
        {
            var stream = this.GetType().Assembly.GetManifestResourceStream("PipelineBuilderClient.Resources.Images.Shortcut.png");

            var bytes = new byte[stream.Length];

            stream.Read(bytes, 0, (int)stream.Length);

            return bytes;
        }

        public T ConvertImage<T>(byte[] imageData)
        {
            var converter = new ByteArrayToBitMapConverter();
            var image = (T)converter.Convert(imageData, typeof(T), null, null);

            return image;
        }


        public SubmitOperation Update(Entity entity)
        {
            throw new NotImplementedException();
        }

        public InvokeOperation Build(string nodeID)
        {
            throw new NotImplementedException();
        }

        public void Refresh()
        {
            throw new NotImplementedException();
        }
    }
}
